﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.AnimationCurve
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine.Bindings;
using UnityEngine.Scripting;

#nullable disable
namespace UnityEngine
{
  /// <summary>
  ///   <para>Store a collection of Keyframes that can be evaluated over time.</para>
  /// </summary>
  [NativeHeader("Runtime/Math/AnimationCurve.bindings.h")]
  [RequiredByNativeCode]
  [StructLayout(LayoutKind.Sequential)]
  public class AnimationCurve : IEquatable<AnimationCurve>
  {
    internal IntPtr m_Ptr;

    [FreeFunction("AnimationCurveBindings::Internal_Destroy", IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void Internal_Destroy(IntPtr ptr);

    [FreeFunction("AnimationCurveBindings::Internal_Create", IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern IntPtr Internal_Create(Keyframe[] keys);

    [FreeFunction("AnimationCurveBindings::Internal_Equals", HasExplicitThis = true, IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern bool Internal_Equals(IntPtr other);

    ~AnimationCurve() => AnimationCurve.Internal_Destroy(this.m_Ptr);

    /// <summary>
    ///   <para>Evaluate the curve at time.</para>
    /// </summary>
    /// <param name="time">The time within the curve you want to evaluate (the horizontal axis in the curve graph).</param>
    /// <returns>
    ///   <para>The value of the curve, at the point in time specified.</para>
    /// </returns>
    [ThreadSafe]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern float Evaluate(float time);

    /// <summary>
    ///   <para>All keys defined in the animation curve.</para>
    /// </summary>
    public Keyframe[] keys
    {
      get => this.GetKeys();
      set => this.SetKeys(value);
    }

    /// <summary>
    ///   <para>Add a new key to the curve.</para>
    /// </summary>
    /// <param name="time">The time at which to add the key (horizontal axis in the curve graph).</param>
    /// <param name="value">The value for the key (vertical axis in the curve graph).</param>
    /// <returns>
    ///   <para>The index of the added key, or -1 if the key could not be added.</para>
    /// </returns>
    [FreeFunction("AnimationCurveBindings::AddKeySmoothTangents", HasExplicitThis = true, IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern int AddKey(float time, float value);

    /// <summary>
    ///   <para>Add a new key to the curve.</para>
    /// </summary>
    /// <param name="key">The key to add to the curve.</param>
    /// <returns>
    ///   <para>The index of the added key, or -1 if the key could not be added.</para>
    /// </returns>
    public int AddKey(Keyframe key) => this.AddKey_Internal(key);

    [NativeMethod("AddKey", IsThreadSafe = true)]
    private int AddKey_Internal(Keyframe key) => this.AddKey_Internal_Injected(ref key);

    /// <summary>
    ///   <para>Moves the key at index to key.time and key.value.</para>
    /// </summary>
    /// <param name="index">The index of the key to move.</param>
    /// <param name="key">The keyframe containing the new time and value.</param>
    /// <returns>
    ///   <para>The index of the keyframe after moving it.</para>
    /// </returns>
    [FreeFunction("AnimationCurveBindings::MoveKey", HasExplicitThis = true, IsThreadSafe = true)]
    [NativeThrows]
    public int MoveKey(int index, Keyframe key) => this.MoveKey_Injected(index, ref key);

    /// <summary>
    ///   <para>Removes a key.</para>
    /// </summary>
    /// <param name="index">The index of the key to remove.</param>
    [FreeFunction("AnimationCurveBindings::RemoveKey", HasExplicitThis = true, IsThreadSafe = true)]
    [NativeThrows]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void RemoveKey(int index);

    public Keyframe this[int index] => this.GetKey(index);

    /// <summary>
    ///   <para>The number of keys in the curve. (Read Only)</para>
    /// </summary>
    public extern int length { [NativeMethod("GetKeyCount", IsThreadSafe = true), MethodImpl(MethodImplOptions.InternalCall)] get; }

    [FreeFunction("AnimationCurveBindings::SetKeys", HasExplicitThis = true, IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void SetKeys(Keyframe[] keys);

    [FreeFunction("AnimationCurveBindings::GetKey", HasExplicitThis = true, IsThreadSafe = true)]
    [NativeThrows]
    private Keyframe GetKey(int index)
    {
      Keyframe ret;
      this.GetKey_Injected(index, out ret);
      return ret;
    }

    [FreeFunction("AnimationCurveBindings::GetKeys", HasExplicitThis = true, IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern Keyframe[] GetKeys();

    /// <summary>
    ///   <para>Smooth the in and out tangents of the keyframe at index.</para>
    /// </summary>
    /// <param name="index">The index of the keyframe to be smoothed.</param>
    /// <param name="weight">The smoothing weight to apply to the keyframe's tangents.</param>
    [FreeFunction("AnimationCurveBindings::SmoothTangents", HasExplicitThis = true, IsThreadSafe = true)]
    [NativeThrows]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SmoothTangents(int index, float weight);

    /// <summary>
    ///   <para>Creates a constant "curve" starting at timeStart, ending at timeEnd, and set to the value value.</para>
    /// </summary>
    /// <param name="timeStart">The start time for the constant curve.</param>
    /// <param name="timeEnd">The end time for the constant curve.</param>
    /// <param name="value">The value for the constant curve.</param>
    /// <returns>
    ///   <para>The constant curve created from the specified values.</para>
    /// </returns>
    public static AnimationCurve Constant(float timeStart, float timeEnd, float value)
    {
      return AnimationCurve.Linear(timeStart, value, timeEnd, value);
    }

    /// <summary>
    ///   <para>A straight Line starting at timeStart, valueStart and ending at timeEnd, valueEnd.</para>
    /// </summary>
    /// <param name="timeStart">The start time for the linear curve.</param>
    /// <param name="valueStart">The start value for the linear curve.</param>
    /// <param name="timeEnd">The end time for the linear curve.</param>
    /// <param name="valueEnd">The end value for the linear curve.</param>
    /// <returns>
    ///   <para>The linear curve created from the specified values.</para>
    /// </returns>
    public static AnimationCurve Linear(
      float timeStart,
      float valueStart,
      float timeEnd,
      float valueEnd)
    {
      if ((double) timeStart == (double) timeEnd)
        return new AnimationCurve(new Keyframe[1]
        {
          new Keyframe(timeStart, valueStart)
        });
      float num = (float) (((double) valueEnd - (double) valueStart) / ((double) timeEnd - (double) timeStart));
      return new AnimationCurve(new Keyframe[2]
      {
        new Keyframe(timeStart, valueStart, 0.0f, num),
        new Keyframe(timeEnd, valueEnd, num, 0.0f)
      });
    }

    /// <summary>
    ///   <para>Creates an ease-in and out curve starting at timeStart, valueStart and ending at timeEnd, valueEnd.</para>
    /// </summary>
    /// <param name="timeStart">The start time for the ease curve.</param>
    /// <param name="valueStart">The start value for the ease curve.</param>
    /// <param name="timeEnd">The end time for the ease curve.</param>
    /// <param name="valueEnd">The end value for the ease curve.</param>
    /// <returns>
    ///   <para>The ease-in and out curve generated from the specified values.</para>
    /// </returns>
    public static AnimationCurve EaseInOut(
      float timeStart,
      float valueStart,
      float timeEnd,
      float valueEnd)
    {
      return (double) timeStart == (double) timeEnd ? new AnimationCurve(new Keyframe[1]
      {
        new Keyframe(timeStart, valueStart)
      }) : new AnimationCurve(new Keyframe[2]
      {
        new Keyframe(timeStart, valueStart, 0.0f, 0.0f),
        new Keyframe(timeEnd, valueEnd, 0.0f, 0.0f)
      });
    }

    /// <summary>
    ///   <para>The behaviour of the animation before the first keyframe.</para>
    /// </summary>
    public extern WrapMode preWrapMode { [NativeMethod("GetPreInfinity", IsThreadSafe = true), MethodImpl(MethodImplOptions.InternalCall)] get; [NativeMethod("SetPreInfinity", IsThreadSafe = true), MethodImpl(MethodImplOptions.InternalCall)] set; }

    /// <summary>
    ///   <para>The behaviour of the animation after the last keyframe.</para>
    /// </summary>
    public extern WrapMode postWrapMode { [NativeMethod("GetPostInfinity", IsThreadSafe = true), MethodImpl(MethodImplOptions.InternalCall)] get; [NativeMethod("SetPostInfinity", IsThreadSafe = true), MethodImpl(MethodImplOptions.InternalCall)] set; }

    /// <summary>
    ///   <para>Creates an animation curve from an arbitrary number of keyframes.</para>
    /// </summary>
    /// <param name="keys">An array of Keyframes used to define the curve.</param>
    public AnimationCurve(params Keyframe[] keys)
    {
      this.m_Ptr = AnimationCurve.Internal_Create(keys);
    }

    /// <summary>
    ///   <para>Creates an empty animation curve.</para>
    /// </summary>
    [RequiredByNativeCode]
    public AnimationCurve() => this.m_Ptr = AnimationCurve.Internal_Create((Keyframe[]) null);

    public override bool Equals(object o)
    {
      if (o == null)
        return false;
      if (this == o)
        return true;
      return o.GetType() == this.GetType() && this.Equals((AnimationCurve) o);
    }

    public bool Equals(AnimationCurve other)
    {
      if (other == null)
        return false;
      return this == other || this.m_Ptr.Equals((object) other.m_Ptr) || this.Internal_Equals(other.m_Ptr);
    }

    public override int GetHashCode() => this.m_Ptr.GetHashCode();

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern int AddKey_Internal_Injected(ref Keyframe key);

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern int MoveKey_Injected(int index, ref Keyframe key);

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void GetKey_Injected(int index, out Keyframe ret);
  }
}
